/* Usage : ./parse Yeast.txt 1 */

#include <stdio.h>
#include <stdlib.h>
#include "infer.h"

struct order_t {
	int size;
	int cap;
	timeorder *ptr;
};
typedef struct order_t order;

void print_help ()
{
	printf ("Usage		: ./parse2 N L processfile gap1 gap2\n");
	printf ("		 (./parse2 11 12 Yeast.txt 1 2)\n\n");
	printf ("N              : number of nodes\n");
	printf ("L              : number of timesteps\n");
	printf ("processfile	: feasible process file\n");
	printf ("gap1		: When checking the order of flips, how many steps can insurance P1>=P2 is right\n\n");
	printf ("gap2		: When checking the order of flips, how many steps can insurance P1>P2 is right\n\n");
	printf ("This program will parse the processes file with size N x L and generate the output file for program infer.\n");
}

static inline void order_new (order* v) {
	v->size = 0;
	v->cap  = 4;
	v->ptr  = (timeorder*)malloc(sizeof(timeorder)*v->cap);
}

static inline void order_push (order* v, timeorder e)
{
	if (v->size == v->cap)
	{
		int newsize = v->cap * 2 + 1;
		v->ptr = (timeorder*)realloc(v->ptr,sizeof(timeorder)*newsize);
		v->cap = newsize;
	}
	v->ptr[v->size].n1    = e.n1;
	v->ptr[v->size].n2    = e.n2;
	v->ptr[v->size].flip1 = e.flip1;
	v->ptr[v->size].flip2 = e.flip2;
	v->ptr[v->size].type  = e.type;
	v->size++;
}

void parse_and_print_flips (int N, int L, int pathway[L][N])
{
	int i, j, T[N];

	for (i = 0; i < N; i++)
	{
		T[i] = 0;
	}

	for (i = 1; i < L - 1; i++)
	{
		for (j = 0; j < N; j++)
		{
			if (pathway[i - 1][j] != pathway[i][j])
			{
				T[j] ++;
			}
		}
	}

	printf ("%d %d\n", N, L);
	for (i = 0; i < N; i++)
	{
		printf ("%d ", pathway[0][i]);
	}
	printf ("\n");
	for (i = 0; i < N; i++)
	{
		printf ("%d ", T[i]);
	}
	printf ("\n");
}

void parse_pathway (int N, int L, int pathway[L][N], int step, int type, order *p)
{
	int i, j, k, n;
	int T1[L - 2][N + 1], T2[L - 2][N], T[N];

	for (i = 0; i < N; i++)
	{
		T[i] = 0;
	}

	for (i = 0; i < L - 2; i ++)
	{
		for (j = 0; j < N; j++)
		{
			T2[i][j] = 0;
		}
	}

	for (i = 1; i < L - 1; i++)
	{
		T1[i - 1][N] = 0;
		for (j = 0; j < N; j++)
		{
			if (pathway[i - 1][j] != pathway[i][j])
			{
				T1[i - 1][T1[i - 1][N]] = j;
				T[j] ++;
				T2[i - 1][T1[i - 1][N]] = T[j];
				T1[i - 1][N] ++;
			}
		}
	}

	timeorder t;

	t.type = type;
	for (i = 0; i < L - 2 - step; i++)
	{
		for (j = 0; j < T1[i][N]; j++)
		{
			for (k = 0; k < T1[i + step][N]; k++)
			{
				if (T1[i][j] != T1[i + step][k])
				{
					t.n1    = T1[i][j];
					t.flip1 = T2[i][j];
					t.n2    = T1[i + step][k];
					t.flip2 = T2[i + step][k];
					order_push (p, t);
				}

			}
		}
	}
}

void print_order (order *p)
{
	int i;
	timeorder *t;

	printf ("%d\n", p->size);
	for (i = 0; i < p->size; i++)
	{
		t = p->ptr + i;
		printf ("%2d %d %2d %d %d\n", t->n1, t->flip1, t->n2, t->flip2, t->type);
	}
}

int main (int argc, char *argv[])
{
	FILE *fp;
	char buf[256];
	int i, j, N, L, step1, step2;

	if (argc == 1)
	{
		print_help ();
		exit (0);
	}

	N = atoi (argv[1]);
	L = atoi (argv[2]);
	step1 = atoi (argv[4]);
	step2 = atoi (argv[5]);

	int pathway[L][N];

	fp = fopen (argv[3], "r");

	while (fgets (buf, 256, fp))
	{
		for (i = 0; i < L; i++)
		{
			for (j = 0; j < N; j++)
			{
				fscanf (fp, "%d", &(pathway[i][j]));
			}
			fgets (buf, 256, fp);
		}
        
		parse_and_print_flips (N, L, pathway);
        
		order p;
		order_new (&p);
        
		if (step1 != 0)
			parse_pathway (N, L, pathway, step1, 0, &p);
		if (step2 != 0)
			parse_pathway (N, L, pathway, step2, 1, &p);
        
		print_order (&p);
	}

	fclose (fp);
}
